﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.IO;
using Microsoft.Win32;
using System.Threading.Tasks;
using System.Threading;

using Core;
using Core.Primitives;

namespace FrontEnd
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private DataField m_field;
        private IEnumerable<SinglePolyline> m_contours;
        private SaveFileDialog m_saveImageFileDoalog = new SaveFileDialog() { Filter = "BMP image|*.bmp|JPEG image|*.jpeg|TIFF image|*.tiff|PNG image|*.png" };

        public bool Smoothing
        {
            get { return (bool)GetValue(SmoothingProperty); }
            set { SetValue(SmoothingProperty, value); }
        }
        public static readonly DependencyProperty SmoothingProperty = DependencyProperty.Register("Smoothing", typeof(bool), typeof(MainWindow), new UIPropertyMetadata(true));

        public float SmoothFactor
        {
            get { return (float)GetValue(SmoothFactorProperty); }
            set { SetValue(SmoothFactorProperty, value); }
        }
        public static readonly DependencyProperty SmoothFactorProperty = DependencyProperty.Register("SmoothFactor", typeof(float), typeof(MainWindow), new UIPropertyMetadata(1.0f));

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Invoke(Action action)
        {
            Dispatcher.Invoke((Delegate)action);
        }
        private void ShowNotification(string header, string text, Color color, TimeSpan ttl)
        {
            PopupBorder.Background = new SolidColorBrush(color);
            PopupHeaderTextBlock.Text = header;
            PopupTextBlock.Text = text;
            PopupControl.IsOpen = true;

            // popup closing
            Task.Factory.StartNew(() =>
                {
                    Thread.Sleep(ttl);
                    Invoke(() => PopupControl.IsOpen = false);
                });
        }
        private void PresentRandomFieldRegionContours_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            Random ramdomGenerator = new Random(Environment.TickCount);

            int w = 20;
            int h = 15;
            int regionAmount = 4;

            m_field = new DataField(w, h);

            for (int i = 0; i < h; i++)
            {
                for (int j = 0; j < w; j++)
                {
                    int type = ramdomGenerator.Next(regionAmount);
                    //int type = Math.Sin(i / 10.0) * Math.Sin(j / 10.0) - 0.3 > 0 ? 0 : 1;

                    m_field[i, j] = new DataPoint(type);
                }
            }

            // for debug
            using (FileStream fileStream = new FileStream("field", FileMode.Create))
            {
                m_field.Save(fileStream);
            }

            //using (FileStream fileStream = new FileStream("field", FileMode.Open))
            //{
            //    m_field = DataField.Load(fileStream);
            //}

            //m_field = DataField.FromTypesArray(
            //    new int[,]
            //    {
            //        {0,1,1,1,1,1,0},
            //        {0,1,1,1,1,1,0},
            //        {0,1,1,1,1,1,0},
            //        {0,0,1,1,1,0,0},
            //        {0,0,1,1,1,0,0},
            //        {0,0,0,1,0,0,0},
            //        {0,0,0,0,0,0,0}
            //    });

            //m_field = DataField.FromTypesArray(
            //    new int[,]
            //    {
            //        {0,0,0},
            //        {0,1,0},
            //        {0,0,0}
            //    });

            m_contours = ConnectedRegionContourFinder
                .GetContours(m_field, ConnectedRegionContourFinder.ConnectivityType.FourConnectivity);

            DataFieldPresenter.BoundingRectangle = m_field.BoundingRectangle;

            PresentContours();
        }
        private void PresentContours()
        {
            if (m_contours == null)
                return;

            if (Smoothing)
                DataFieldPresenter.Contours = m_contours.Select(c => Smoother.Smooth(m_field, c));
            else
                DataFieldPresenter.Contours = m_contours;
        }
        private void SavePicture_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            try
            {
                if (m_saveImageFileDoalog.ShowDialog() == true)
                {
                    BitmapEncoder encoder;

                    string extension = System.IO.Path.GetExtension(m_saveImageFileDoalog.FileName);
                    switch (extension.ToLower())
                    {
                        case ".bmp":
                            encoder = new BmpBitmapEncoder();
                            break;
                        case ".jpeg":
                            encoder = new JpegBitmapEncoder();
                            break;
                        case ".tiff":
                            encoder = new TiffBitmapEncoder();
                            break;
                        case ".png":
                            encoder = new PngBitmapEncoder();
                            break;
                        default:
                            MessageBox.Show("Unknown image format specified");
                            return;
                    }

                    using (Stream stream = m_saveImageFileDoalog.OpenFile())
                    {
                        ControlCaptureHelper.SaveFrameworkElement(DataFieldPresenter, encoder, stream);
                    }

                    ShowNotification(
                        "Success", 
                        string.Format("{0} was successfuly created", 
                        m_saveImageFileDoalog.SafeFileName), 
                        Color.FromArgb(225, 225, 255, 225), 
                        TimeSpan.FromSeconds(5));
                }
            }
            catch (Exception exc)
            {
                ShowNotification(
                    "Error", 
                    exc.Message, 
                    Color.FromArgb(225, 255, 225, 225),
                    TimeSpan.FromSeconds(3));
            }
            
        }
        private void Close_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            Close();
        }
        private void ShowPopup(object sender, RoutedEventArgs e)
        {            
            PopupControl.IsOpen = true;            
        }
        private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            PopupControl.IsOpen = false;
        }
    }
}
